Order of Processing
A single request can match more than one behavior. When it does, IO River applies all of the matching behaviors, one by one, in the order in which the behaviors are listed in your service. This page explains how the order works, how matching behaviors combine, and how to control the result.
How behaviors are processed
For every request, IO River goes through the following steps:
- The default behavior is always applied first. It matches all traffic.
- Then it goes through your other behaviors from the first to the last in the list. Each behavior whose path pattern matches the request is applied; behaviors that do not match are skipped.
- If a matching behavior has an immediate action, the processing stops there: the behaviors listed after it are not applied.
- Otherwise, the result is the combination of everything that was applied, in that order.
This is called a multi-match approach: a request is not handled by only the first (or the most specific) matching behavior, but by all of them.
The order is the order of the list, not the structure of the path patterns. A behavior with a more specific path pattern, such as /api/v2/*, does not run after a behavior with a broader pattern, such as /api/*, unless it is listed after it.
How matching behaviors combine
When several behaviors are applied to the same request, there are two cases:
- Different actions are combined. If one behavior sets a cache TTL and another one adds a response header, the request gets both.
- The same action more than once: the last one wins. If two behaviors that match the request define the same action (for example, both set the cache TTL, or both set the same response header), the behavior that runs later in the list takes precedence over the earlier one. The earlier behavior still applies for everything it defines that the later one doesn't.
The default behavior is always first, so any matching behavior can override the value it defines.
Immediate actions
Most actions only add to the request. A few actions are different: they decide how the request is answered, so there is nothing left for the following behaviors to do. These are called immediate actions. When an immediate action is triggered for a request, the behaviors listed after it are not applied to that request.
The immediate actions are:
Behaviors that are listed before the behavior with the immediate action have already been processed. This is one more reason why the order matters: a behavior with an immediate action should be listed after the behaviors that you still want to be applied to the same requests, and a broad behavior with an immediate action listed early can prevent the behaviors after it from ever being applied.
Deny Access By IP and Deny Access By Time stop the processing only for the requests they act on, for example a request from one of the listed IP addresses, or a request that arrives during the deny period. For all other requests the action does nothing and the processing continues with the next behavior.
Examples
All the examples use the following list of behaviors, in this order:
| # | Behavior | Path pattern | Action |
|---|---|---|---|
| Default | all traffic | Cache TTL: 1 day | |
| 1 | B1 | /api/* | Cache TTL: 60 seconds |
| 2 | B2 | /api/v2/* | Cache TTL: 120 seconds |
| 3 | B3 | /static/* | Add response header X-Asset: true |
Example 1: a request that matches several behaviors
A request for /api/v2/users matches the default behavior, B1 and B2. It does not match B3.
The behaviors are applied in this order:
- Default: cache TTL 1 day
- B1: cache TTL 60 seconds
- B2: cache TTL 120 seconds
Both B1 and B2 set the cache TTL, and B2 runs last, so the cache TTL that is used is 120 seconds.
Example 2: a request that matches one behavior
A request for /api/v1/orders matches the default behavior and B1. It does not match B2 (/api/v2/*) or B3.
- Default: cache TTL 1 day
- B1: cache TTL 60 seconds
The cache TTL that is used is 60 seconds.
Example 3: different actions are combined
A request for /static/logo.png matches the default behavior and B3.
- Default: cache TTL 1 day
- B3: add response header
X-Asset: true
B3 doesn't define a cache TTL, so the default behavior's TTL of 1 day still applies, and the response also includes the X-Asset: true header. Nothing is overridden, because the two behaviors define different actions.
Example 4: the same list in a different order
The order is what decides the result. Take the same behaviors B1 and B2, but with B2 listed before B1:
| # | Behavior | Path pattern | Action |
|---|---|---|---|
| Default | all traffic | Cache TTL: 1 day | |
| 1 | B2 | /api/v2/* | Cache TTL: 120 seconds |
| 2 | B1 | /api/* | Cache TTL: 60 seconds |
Now a request for /api/v2/users is handled like this:
- Default: cache TTL 1 day
- B2: cache TTL 120 seconds
- B1: cache TTL 60 seconds
B1 runs last, so the cache TTL that is used is 60 seconds, even though B2 has the more specific path pattern.
Example 5: the same response header from two behaviors
Two behaviors that match /promo/* and /promo/summer/* both set the response header X-Campaign:
| # | Behavior | Path pattern | Action |
|---|---|---|---|
| 1 | Promo | /promo/* | Set response header X-Campaign: general |
| 2 | Summer | /promo/summer/* | Set response header X-Campaign: summer |
- A request for
/promo/winter/banner.pngmatches only Promo:X-Campaign: general. - A request for
/promo/summer/banner.pngmatches both. Summer runs last, so the response includesX-Campaign: summer.
Example 6: an immediate action stops the following behaviors
Take the following list of behaviors:
| # | Behavior | Path pattern | Action |
|---|---|---|---|
| Default | all traffic | Cache TTL: 1 day | |
| 1 | Blog redirect | /blog/* | Redirect to URL: https://blog.example.com |
| 2 | Blog archive | /blog/archive/* | Cache TTL: 1 hour |
A request for /blog/archive/2020 matches the default behavior, Blog redirect and Blog archive:
- Default: cache TTL 1 day
- Blog redirect: redirect to
https://blog.example.com. This is an immediate action, so the processing stops here. - Blog archive: not applied
The visitor receives the redirect. The cache TTL of Blog archive is never applied, because Blog redirect is listed before it.
If Blog archive is listed before Blog redirect, both behaviors are applied: first the cache TTL of 1 hour, and then the redirect.
Example 7: Deny Access By IP
| # | Behavior | Path pattern | Action |
|---|---|---|---|
| 1 | Admin | /admin/* | Deny Access By IP: 203.0.113.0/24 |
| 2 | Admin public | /admin/public/* | Add response header X-Area: public |
- A request for
/admin/public/help.htmlfrom203.0.113.7matches both behaviors. Admin is listed first and denies the request, so the processing stops and Admin public is not applied. - The same request from
198.51.100.20doesn't match the denied IP addresses, so Admin does nothing. The processing continues, Admin public is applied, and the response includesX-Area: public.
Controlling the order
The order of the behaviors is yours to define. It matters whenever two behaviors that can match the same request define the same action, and whenever one of them has an immediate action.
To change the order in the dashboard:
- Go to your service and open the Behaviors page.
- Click REORDER.
- Drag the behaviors into the order you want. The number next to each behavior is its position: the behavior at position 1 runs first, and the last one runs last.
- Save your changes.
The default behavior is not part of the list. It always runs first.
If you configure your services through the API, the order is the order of the behaviors in the list in the service configuration.
When a broad behavior and a more specific behavior set the same action, list the broader behavior first and the more specific one after it. The specific behavior then takes precedence for the paths it matches, and the broad behavior applies to everything else.
List behaviors with an immediate action (a redirect or a deny rule) after the behaviors that should still be applied to the same requests.